#ifndef _LJMU_DX10_BASEAPP_H_
#define _LJMU_DX10_BASEAPP_H_

#include "cljmudx10manager.h"
#include "cljmudx10winapp.h"
#include <d3dx10math.h>
#include <string>


/*********************************
* Base Application Class which is
* to be extended to produce your
* game application.
*
* AUTHOR: CHRIS CARTER
**********************************/
class CDX10BaseApplication
{
	public:
		//-----------CONSTRUCTORS AND DESTRUCTORS--------------------------------
		CDX10BaseApplication(): _obj_dxman(NULL),_obj_wndapp(NULL)
		{
			initDefaultValues();
		}			//Constructor for the Initial Application
		virtual ~CDX10BaseApplication(){}										//Blank Destructor (Virtual)

		//-----------PUBLIC METHODS----------------------------------------------
		virtual bool initialise();												//Initialise our application
		virtual bool update();													//Update our application
		virtual bool render();													//Allow us to override the Default Rendering Behaviour
		virtual void cleanup();													//Cleanup our Application - This method can be optionally overriden to cleanup dynamic game objects
																				
		
		//-----------ABSTRACT CLASS METHODS--------------------------------------
		virtual bool customInit() = 0;											//This Method is to be Overridden in our concrete game implementation - put the IA stage code here.
		virtual bool customUpdate() = 0;										//This Method is to be Overridden in our concrete game implementation - put game logic here
		virtual bool customRender() = 0;										//This Method is to be Overridden in our concrete game implementation - put rendering logic here
		virtual bool customCleanup() = 0;										//This Method is to be Overridden in our concrete game implementation - put the clean up logic here
		virtual LRESULT CALLBACK customWndProc(HWND pwindowhandle, UINT pmessagetype, WPARAM pwparam, LPARAM plparam) = 0; //This Method is to be Overridden in our game - put WinProc code here. 

		//-----------ACCESSORS/MUTATORS------------------------------------------
		int		getScreenWidth();												//Get the Screen Width.
		int		getScreenHeight();												//Get the Screen Height.
		int		getPreferredScreenWidth();										//Get the Preferred Screen Width.
		int		getPreferredScreenHeight();										//Get the Preferred Screen Height.
		LPWSTR  getAppName();												    //Get the Application Name.
		bool    isFullScreen();													//Is Application in Full Screen?.
		bool	isVSyncEnabled();												//Is Vertical Monitor Sync Enabled?.
		float   getCamNearPlane();												//Get the Near Plane of the Camera Frustum.
		float   getCamFarPlane();												//Get the Far Plane of the Camera Frustum.
		D3DXCOLOR getColour();													//Get the Background Colour.
		bool    isCursorVisible();												//Is the Mouse Cursor Visible?.
		std::wstring  getShaderDataDir();										//Get the Data Directory For Shaders
		std::wstring  getImageDataDir();										//Get the Data Directory For Images.
		std::wstring  getSpriteDataDir();										//Get the Data Directory For Sprites.
		std::wstring  getAudioDataDir();										//Get the Data Directory For Audio.
				
		bool    setWindowManager(CDX10WindowsApplication* pwndapp);				//Associate the Window Manager with this app.
		bool	setPrefScreenDimensions(int pscreenwidth, int pscreenheight);	//Set the Preferred Screen Dimensions.
		bool	setScreenDimensions(int pscreenwidth, int pscreenheight);		//Set the Actual Screen Dimensions.
		void    setFullScreen(bool pisfull);									//Set the Screen Mode to Full Screen.
		void    setVSyncEnabled(bool penabled);									//Set the Screen Mode to Vertical Sync Enabled.
		void    setAppName(LPWSTR pname);										//Set the Application Name.
		void    setCamNearPlane(float pnear);									//Set the Near Plane of the Camera Frustum.
		void    setCamFarPlane(float pfar);										//Set the Far Plane of the Camera Frustum.
		void    setBGColour(float pred,float pgreen,float pblue,float palpha);	//Set the Background Clear Colour.
		void    setCursorVisible(bool pvisible);								//Set the Status of the Mouse Cursor Visibility.
		void    setShaderDataDir(std::wstring pshaderdata);						//Set the Data Directory where shaders are held.
		void    setImageDataDir(std::wstring pimgdata);							//Set the Data Directory where Images are held.
		void    setSpriteDataDir(std::wstring pimgdata);						//Set the Data Directory where Sprites are held;
		void    setAudioDataDir(std::wstring pimgdata);							//Set the Data Directory where Audio Files are held;

	protected:
		//Set the Default Values of our Application Properties
		void initDefaultValues()
		{
			_prop_fullscreen		= false;
			_prop_vsync				= false;
			_prop_pref_screenwidth	= 600;
			_prop_pref_screenheight = 800;
			_prop_screenheight		= 0;
			_prop_screenwidth       = 0;
			_prop_cam_near			= 0.1f;
			_prop_cam_far			= 1000.0f;
			_prop_app_name			= L"DX10BaseApp";
			_prop_bg_colour		    = D3DXCOLOR(0,0,0,1);
		}
	protected:
		//-----------INTERNAL FIELD MEMBERS-------------------------------------
		CDX10Manager*			 _obj_dxman;				//Pointer to the DirectX Application Manager
		CDX10WindowsApplication* _obj_wndapp;				//Pointer to the Windows Application Manager
		bool					 _prop_fullscreen;			//Is the Application to be displayed in full screen mode?
		bool					 _prop_vsync;				//Is the Application Synchronised to Vertical Refresh Rate?
		bool					 _prop_cursor;				//Is the Mouse Cursor Visible?
		unsigned int			 _prop_pref_screenwidth;	//Application's Preferred Screen Width
		unsigned int			 _prop_pref_screenheight;	//Application's Preferred Screen Height
		unsigned int			 _prop_screenwidth;			//Application's Actual Screen Width
		unsigned int			 _prop_screenheight;		//Application's Actual Screen Height
		float					 _prop_cam_near;			//Application's Near Plane of the View Frustum.
		float					 _prop_cam_far;				//Application's Far Plane of the View Frustum.
		LPWSTR					 _prop_app_name;			//Application's Name
		std::wstring			 _prop_shader_dir;			//Directory For Shaders
		std::wstring			 _prop_img_dir;				//Directory For Shaders
		std::wstring			 _prop_audio_dir;			//Directory For Shaders
		std::wstring			 _prop_sprite_dir;			//Directory For Shaders
		D3DXCOLOR 				 _prop_bg_colour;			//Background Colour of the Application.
		D3DXMATRIX				 _dx_mat_ortho;				//Orthographic Camera Matrix For 2D rendering.
		D3DXMATRIX				 _dx_mat_view;				//View Matrix For 2D rendering.
};

//--------------INLINE GETTER IMPLEMENTATIONS----------------------------------------------------------------------

/******************************************
* Get the Background Colour Used on the
* Back Buffer.
******************************************/
inline D3DXCOLOR CDX10BaseApplication::getColour()
{
	return _prop_bg_colour;
}

/******************************************
* Get the Width of the Screen Resolution
* In Pixels.
******************************************/
inline int CDX10BaseApplication::getScreenWidth()
{
	if(this->_prop_screenwidth > 0)
		return this->_prop_screenwidth;
	return this->_prop_pref_screenwidth;
}

/******************************************
* Get the Height of the Screen Resolution
* In Pixels.
******************************************/
inline int CDX10BaseApplication::getScreenHeight()
{
	if(this->_prop_screenheight > 0)
		return this->_prop_screenheight;
	return this->_prop_pref_screenheight;
}

/******************************************
* Get the Preferred Screen Resolution Width
* In Pixels.
******************************************/
inline int CDX10BaseApplication::getPreferredScreenWidth()
{
	return this->_prop_pref_screenwidth;
}

/******************************************
* Get the Preferred Screen Resolution Height
* In Pixels.
******************************************/
inline int CDX10BaseApplication::getPreferredScreenHeight()
{
	return this->_prop_pref_screenheight;
}	

/******************************************
* Get the Application Name.
******************************************/
inline LPWSTR CDX10BaseApplication::getAppName()
{
	return this->_prop_app_name;
}

/******************************************
* Returns True if we are fullscreen, false
* otherwise.
******************************************/
inline bool CDX10BaseApplication::isFullScreen()
{
	return this->_prop_fullscreen;
}

/******************************************
* Returns True if we are synced to Vertical
* refresh rate of the monitor, false otherwise.
******************************************/
inline bool CDX10BaseApplication::isVSyncEnabled()
{
	return this->_prop_vsync;
}

/******************************************
* Returns the Z-Position of the Near Plane
* of the View Frustum.
******************************************/
inline float CDX10BaseApplication::getCamNearPlane()
{
	return this->_prop_cam_near;
}

/******************************************
* Returns the Z-Position of the Far Plane
* of the View Frustum.
******************************************/
inline float CDX10BaseApplication::getCamFarPlane()
{
	return this->_prop_cam_far;
}

/******************************************
* Sets whether the Mouse Cursor is Visible
* or Not.
******************************************/
inline bool CDX10BaseApplication::isCursorVisible()
{
	return this->_prop_cursor;
}

/******************************************
* Get the Shader Data Directory.
******************************************/
inline std::wstring  CDX10BaseApplication::getShaderDataDir()
{
	return this->_prop_shader_dir;
}

/******************************************
* Get the Image Data Directory.
******************************************/
inline std::wstring  CDX10BaseApplication::getImageDataDir()
{
	return this->_prop_img_dir;
}

/******************************************
* Get the Sprite Data Directory.
******************************************/
inline std::wstring  CDX10BaseApplication::getSpriteDataDir()
{
	return this->_prop_sprite_dir;
}

/******************************************
* Get the Audio Data Directory.
******************************************/
inline std::wstring  CDX10BaseApplication::getAudioDataDir()
{
	return this->_prop_audio_dir;
}

//--------------INLINE SETTER IMPLEMENTATIONS----------------------------------------------------------------------

/******************************************
* Associates the Game Application with the
* Windows Application Manager.  This creates
* a bi-directional link where we can access
* the Windows Manager Resources.
******************************************/
inline bool CDX10BaseApplication::setWindowManager(CDX10WindowsApplication* pwndapp)
{
	if(pwndapp != NULL)
	{
		this->_obj_wndapp = pwndapp;
		return true;
	}
	return false;
}

/******************************************
* Sets the Preferred Resolution of the
* Screen.
******************************************/
inline bool CDX10BaseApplication::setPrefScreenDimensions(int pscreenwidth, int pscreenheight)
{
	if(pscreenwidth > 0 && pscreenheight > 0)
	{
		this->_prop_pref_screenwidth	= pscreenwidth;
		this->_prop_pref_screenheight	= pscreenheight;
		return true;
	}
	return false;
}

/******************************************
* Sets the Preferred Resolution of the
* Screen.
******************************************/
inline bool CDX10BaseApplication::setScreenDimensions(int pscreenwidth, int pscreenheight)
{
	if(pscreenwidth > 0 && pscreenheight > 0)
	{
		this->_prop_screenwidth		= pscreenwidth;
		this->_prop_screenheight	= pscreenheight;
		return true;
	}
	return false;
}

/******************************************
* Sets the Colour of the Back Buffer 
* via the component colours (e.g. White = 1,1,1,1
* and black = 0,0,0,1).
******************************************/
inline void CDX10BaseApplication::setBGColour(float pred,float pgreen,float pblue,float palpha)
{
	_prop_bg_colour.r = pred;
	_prop_bg_colour.g = pgreen;
	_prop_bg_colour.b = pblue;
	_prop_bg_colour.a = palpha;
}

/******************************************
* Sets the Application into Full Screen Mode.
******************************************/
inline void CDX10BaseApplication::setFullScreen(bool pisfull)
{
	this->_prop_fullscreen = pisfull;
}

/******************************************
* Set the Application into VSync Mode.
******************************************/
inline void CDX10BaseApplication::setVSyncEnabled(bool penabled)
{
	this->_prop_vsync = penabled;
}

/******************************************
* Sets the Name of this Application.
******************************************/
inline void CDX10BaseApplication::setAppName(LPWSTR pname)
{
	this->_prop_app_name = pname;
}

/******************************************
* Sets the Z Position of the Near Plane of
* the Camera View Frustum.
******************************************/
inline void CDX10BaseApplication::setCamNearPlane(float pnear)
{
	this->_prop_cam_near = pnear;
}

/******************************************
* Sets the Z Position of the Far Plane of
* the Camera View Frustum.
******************************************/
inline void CDX10BaseApplication::setCamFarPlane(float pfar)
{
	this->_prop_cam_far = pfar;
}

/******************************************
* Sets the Mouse Cursor Status to Visible
* or Not.
******************************************/
inline void CDX10BaseApplication::setCursorVisible(bool pvisible)
{
	this->_prop_cursor = pvisible;
}

/******************************************
* Set the Shader Data Directory.
******************************************/
inline void  CDX10BaseApplication::setSpriteDataDir(std::wstring pspritedir)
{
	this->_prop_sprite_dir = pspritedir;
}

/******************************************
* Set the Shader Data Directory.
******************************************/
inline void  CDX10BaseApplication::setImageDataDir(std::wstring pimgdir)
{
	this->_prop_img_dir = pimgdir;
}

/******************************************
* Set the Shader Data Directory.
******************************************/
inline void  CDX10BaseApplication::setShaderDataDir(std::wstring pshaderdir)
{
	this->_prop_shader_dir = pshaderdir;
}

/******************************************
* Set the Shader Data Directory.
******************************************/
inline void  CDX10BaseApplication::setAudioDataDir(std::wstring paudiodir)
{
	this->_prop_audio_dir = paudiodir;
}

#endif